/*
 * The gTree filesystem
 *
 * Copyright (c) 2019 DengGuozu
 *
 * Licensed under the Apache License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
#include "gfs_api.h"


#ifdef GTREE_FILE_COURCE

//----------------------windows Mutex---------------------------------------
static HANDLE mutexGfs = NULL;
#define GFS_MUTEX_CREAT()	mutexGfs=CreateSemaphoreA(NULL, 1, 1, "GfsSemaphore")
#define GFS_MUTEX_DELETE()	CloseHandle(mutexGfs)
#define GFS_MUTEX_LOCK()	WaitForSingleObject(mutexGfs, INFINITE)
#define GFS_MUTEX_UNLOCK()	ReleaseSemaphore(mutexGfs, 1, NULL)



void gfs_evn_init()
{
	GFS_MUTEX_CREAT();
}


#define GFS_PATH_TAG				('/')
//========文件路径检查===返回 1,文件路径，-1非文件夹，字符不匹配，0 匹配文件------
int gfs_strcmp_path(u8* pPath,u8* strTag,u8 pathTag)
{
	if(strTag==NULL)
	{
		while(*pPath != '\0' && *pPath != pathTag) pPath++;
		if(*pPath == pathTag)
			return 1;
		return 0;
	}
	
	while(*strTag)
	{
		if(*pPath != *strTag)
			return -1;
		pPath++;
		strTag++;
	}
	if(*pPath == pathTag)
		return 1;
	if(*pPath)	//后面还有文件名
		return -1;
	return 0;
}



int Incekxor(u8* destin,u8* source,int len)
{
	while(len--) {
		if ((*source & *destin) ^ *source)
			return (((int)*destin << 8)|*source);
		source++; destin++;
	}
	return 0;
}


//================================================================================
static DfGTreeFsBasi gBasiGlobal={0};

int gfs_BalancedGlobalSave(int pNew)
{
	u32 Addr;
	int ret=-1;
	u16 i,max,Esblock[GFS_FILE_HDNM];
	u16 maxIndex,blockNum;
	DfGTreeFsGlobal gGlobalOldeData;
	blockNum = GFS_BLOCK_SIZE/sizeof(DfGTreeFsGlobal);
	maxIndex = gBasiGlobal.gfsCoutSize*blockNum;
	max=0;
	if(gBasiGlobal.g.t.flagClear != 0xFF) {
		pNew=1;
		gBasiGlobal.g.t.flagClear = 0xFF;
	}
	for(i=0;i<maxIndex;i++) {
		if(pNew) {
			gBasiGlobal.gfsCoutIndex++;
			if(gBasiGlobal.gfsCoutIndex >= maxIndex) {
				gBasiGlobal.gfsCoutIndex=0;
				if(max < (sizeof(Esblock)/sizeof(Esblock[0])))
					Esblock[max++] = gBasiGlobal.gfsCoutSize-1;	//End
			}
			else if((gBasiGlobal.gfsCoutIndex % blockNum) == 0) {
				if(max < (sizeof(Esblock)/sizeof(Esblock[0]))) {
					if(gBasiGlobal.gfsCoutIndex == 0)
						Esblock[max++] = gBasiGlobal.gfsCoutSize-1;	//End
					else
						Esblock[max++] = (gBasiGlobal.gfsCoutIndex/blockNum) -1;	//0~n
				}
			}
			//----不做实实记录，减少擦除-----
			gBasiGlobal.g.t.index = gBasiGlobal.gfsNewIndex;
		}
		//TRACE("---BalancedGlobalSave gfsCoutIndex[%d]--\r\n",gBasiGlobal.gfsCoutIndex);
		Addr=gBasiGlobal.gfsCoutStart*GFS_BLOCK_SIZE + (sizeof(DfGTreeFsGlobal)*gBasiGlobal.gfsCoutIndex);
		ret = SPI_Flash_Write(Addr,&gBasiGlobal.g,sizeof(gBasiGlobal.g));
		if(sizeof(gBasiGlobal.g) != ret) {
			LG("DATA Flash Write[%d]->[%d]\r\n",sizeof(gBasiGlobal.g),ret);
			#ifdef GTREE_FILE_ERR_RECORD
			SaveGlobalErr++;
			#endif
			continue;
		}
		ret = SPI_Flash_Read(Addr,&gGlobalOldeData,sizeof(gGlobalOldeData));
		if(sizeof(gGlobalOldeData) != ret) {
			LG("DATA Flash Read[%d]->[%d]\r\n",sizeof(gGlobalOldeData),ret);
			#ifdef GTREE_FILE_ERR_RECORD
			SaveGlobalErr++;
			#endif
			continue;
		}
		if(memcmp_u32((u32*)&gBasiGlobal.g ,(u32*)&gGlobalOldeData,sizeof(DfGTreeFsGlobal)/sizeof(u32))) {
			if(pNew == 0) {
				LG("BalancedGlobalSave->pNew[%d]\r\n",pNew);
			}
			pNew=1;	
			#ifdef GTREE_FILE_ERR_RECORD
			SaveGlobalErr++;
			#endif
			LG_HEX("SPI Flash_Write",&gBasiGlobal.g, sizeof(DfGTreeFsGlobal));
			LG_HEX("SPI Flash_Read",&gGlobalOldeData,sizeof(gGlobalOldeData));
			continue;
		}
		//TRACE("Global Write[%x]->[%d] [%X][%d] OK\r\n",Addr,gBasiGlobal.gfsCoutIndex,gBasiGlobal.g.t.head,gBasiGlobal.g.t.flagG);
		ret = sizeof(DfGTreeFsGlobal);
		break;
	}
	//----------------检查是否有察除块------------------------
	for(i=0;i<max;i++) {
		SPI_Flash_ERASE_SECTOR(FLASH_SECTOR_SIZE*(gBasiGlobal.gfsCoutStart+ Esblock[i]));
		#ifdef GTREE_FILE_ERR_RECORD
		gfs_erase_Global++;
		#endif
		//SPI_Flash_OneSector(gBasiGlobal.gfsCoutStart+ Esblock[i]);
	}
	if(ret < 0) {
		LG("******BalancedGlobalSave*Err*[max=%d]****\r\n",max);
	}
	return ret;
}

void gfs_ClearNullBit(u16 Index)
{
	if(Index == GFS_INDEX_NULL)	//遇到一个 GFS_INDEX_NULL 就跳出来
		return;
	u16 ei = Index/(sizeof(gBasiGlobal.g.NullBit[0])*8);
	if(ei >= (sizeof(gBasiGlobal.g.NullBit)/sizeof(gBasiGlobal.g.NullBit[0]))) {
		LG("gfs ClearNullBit EraseBlock[%d] tobig Err\r\n", Index);
		return;
	}
	u16 b = Index % (sizeof(gBasiGlobal.g.NullBit[0])*8);
	gBasiGlobal.g.NullBit[ei] |= (0x01<<b);
}

int gfs_RecordErase(u16 IndexArray)
{
	u16 ei,b;
	if(IndexArray == GFS_INDEX_NULL)	//遇到一个 GFS_INDEX_NULL 就跳出来
		return -1;
	ei = IndexArray/(sizeof(gBasiGlobal.g.EraseBit[0])*8);
	if(ei >= (sizeof(gBasiGlobal.g.EraseBit)/sizeof(gBasiGlobal.g.EraseBit[0]))) {
		LG("gfs RecordDelete EraseBlock[%d] tobig Err\r\n", IndexArray);
		return -2;
	}
	b = IndexArray % (sizeof(gBasiGlobal.g.EraseBit[0])*8);
	/*
	if(!(gBasiGlobal.g.EraseBit[ei] & (0x01<<b)))
	{
		TRACE("*** RecordErase [%d]", IndexArray);
	}*/
	gBasiGlobal.g.EraseBit[ei] &= ~(0x01<<b);
	return 0;
}

//==================================================================================================

int gfs_FsReadblock(u16 block,u16 offset,void* buff,u16 size)
{
	u32 Addr=(gBasiGlobal.gfsBlockStart+block)*GFS_BLOCK_SIZE + offset;
	return SPI_Flash_Read(Addr,buff,size);
}

int gfs_FsWriteblock(u16 block,u16 offset,void* buff,u16 size)
{
	u32 Addr=(gBasiGlobal.gfsBlockStart+block)*GFS_BLOCK_SIZE + offset;
	if(size == SPI_Flash_Write(Addr,buff,size)) { //-校验写入是否正确---
		u8 CheckBuff[GFS_BLOCK_SIZE],*pTag=(u8*)buff;
		u16 i;
		SPI_Flash_Read(Addr,CheckBuff,size);
		for(i=0;i<size;i++) {
			if(pTag[i] != CheckBuff[i]) {
				LG("**FsWriteblock[%d.%d]->[%d],[%02X->%02X]\r\n",block,offset,i,CheckBuff[i],pTag[i]);
				return i;
			}
		}
		return size;
	}
	return -1;
}

int gfs_FsEraseblock(u16 block)
{
//	TRACE("----gfs Eraseblock block[%d]----",block);
	return SPI_Flash_ERASE_SECTOR((gBasiGlobal.gfsBlockStart+block)*FLASH_SECTOR_SIZE);
}
//================================================================================

#ifdef GFS_MEDIAN_SCAN
u16 gfs_GetNewGuide(void)
{
	if(gBasiGlobal.gfsBlockSize == 0)	
		return GFS_INDEX_NULL;
	if(gBasiGlobal.g.PreMax < GFS_FILE_MAX) {
		gBasiGlobal.g.PreMax++;
		return GFS_BASIC_DATA;
	}
	LG("gfs GetNewBlockNum i[%d] Err OK\r\n",gBasiGlobal.g.PreMax);
	return GFS_INDEX_NULL;
}

void gfs_FreeIndexGuide(u16 iGuide,u16 iEntry)
{
	if(iGuide > GFS_FILE_MAX) {
		gBasiGlobal.g.PreMax--;
		gfs_ClearNullBit(iEntry);
		return;
	}
	SetInversBlock(iEntry);
	if(iEntry != gBasiGlobal.g.BlockIndex[iGuide])
	{//同时操作多个文件会出现对应不上的问题
		for(iGuide=0; iGuide<GFS_FILE_MAX; iGuide++) {
			if(iEntry == gBasiGlobal.g.BlockIndex[iGuide])
				break;
		}
		if(iGuide >= GFS_FILE_MAX) {
			LG("***FreeIndexGuide iEntry[%d] max[%d] Err\r\n",iEntry,iGuide);
			//gBasiGlobal.g.PreMax--;
			return;
		}
	}
	for(;iGuide<(GFS_FILE_MAX-1);iGuide++) {
		gBasiGlobal.g.BlockIndex[iGuide]=gBasiGlobal.g.BlockIndex[iGuide+1];
	}
	gBasiGlobal.g.BlockIndex[iGuide] = GFS_INDEX_NULL;
	gBasiGlobal.g.BlockMax--;
	gBasiGlobal.g.PreMax--;
}

u16 gfs_median_block_loadnew(u16 *pIndexGuide,u16 oldIndex,u16 newIndex,char *pFilepath)
{
	int ret;
	DfGTreeFsFileName tName;
	u16 left,right,middle,iGuide;
	if(oldIndex == newIndex && *pIndexGuide < GFS_FILE_MAX)
		return 0;
	iGuide=*pIndexGuide;
	SetInversBlock(oldIndex);
	SetInversBlock(newIndex);
	GFS_MUTEX_LOCK();
	if(iGuide < GFS_FILE_MAX) { //----更新旧入口------
		if(gBasiGlobal.g.BlockIndex[iGuide] != oldIndex) {
			right = gBasiGlobal.g.BlockMax;
			for(iGuide=0;iGuide<right;iGuide++) {
				if(gBasiGlobal.g.BlockIndex[iGuide] == oldIndex) break;
			}
			if(iGuide >= right) {
				GFS_MUTEX_UNLOCK();
				LG("###MedianSaveLoad IndexGuide[%d]BlockMax[%d] Err\r\n",iGuide,right);
				return GFS_INDEX_NULL;
			}
			*pIndexGuide = iGuide;
		}
		gBasiGlobal.g.BlockIndex[iGuide]=newIndex;
		GFS_MUTEX_UNLOCK();
		if(newIndex == (oldIndex&newIndex))
			return 0;
		return 1;
	}
	if(gBasiGlobal.g.BlockMax < GFS_FILE_MAX) {
		//--------------NewAdd-----------------------
		right= gBasiGlobal.g.BlockMax;
		left = 0;
		while(left < right) {
			middle = (right+left)>>1;
			gfs_FsReadblock(InversBlock(gBasiGlobal.g.BlockIndex[middle]),0,tName.filepath,sizeof(tName.filepath));
			ret = strcmp(pFilepath,tName.filepath);
			if(ret == 0) break;
			if(ret > 0)
				left = middle+1;
			else
				right = middle;
		}
		middle = (right+left)>>1;
		for(right= gBasiGlobal.g.BlockMax;right>middle;right--) {
			gBasiGlobal.g.BlockIndex[right]=gBasiGlobal.g.BlockIndex[right-1];
		}
		gBasiGlobal.g.BlockIndex[middle] = newIndex;
		*pIndexGuide = middle;
		gBasiGlobal.g.BlockMax++;
		GFS_MUTEX_UNLOCK();
		//if(middle == (gBasiGlobal.g.t.BlockMax++))	//最后一个，BlockMax需要自加
		//	return 0;	//后添加
		return 1;	
	}
	GFS_MUTEX_UNLOCK();
	LG("###MedianSaveLoad PreMax[%d]BlockMax[%d] Err\r\n",gBasiGlobal.g.PreMax,gBasiGlobal.g.BlockMax);
	return GFS_INDEX_NULL;
}

u16 gfs_ScanFileName(gFsNameUnit *pName,const char *path)
{
	int ret;
	u16 left,right,middle;
	if(gBasiGlobal.gfsBlockSize == 0)	
		return GFS_INDEX_NULL;
	right= gBasiGlobal.g.BlockMax;
	left = 0;
	while(left < right) {
		middle = (right+left)>>1;
		gfs_FsReadblock(InversBlock(gBasiGlobal.g.BlockIndex[middle]),0,pName,sizeof(DfGTreeFsFileName));
		ret = strcmp(path,pName->f.filepath);
		if(ret == 0) return middle;
		if(ret > 0)
			left = middle+1;
		else
			right = middle;
	}
	return GFS_INDEX_NULL;
}

void Gfs_MedianInitCheck(void)
{
	DfGTreeFsFileName tName1,tName2;
	u16 Index;
	u8	i,j;
	if(gBasiGlobal.g.BlockMax <= GFS_FILE_MAX) {
		#ifdef INDEX_COUNT_DOWN	//纠正原来空间地址
		j = 0;
		for(i=0;i<gBasiGlobal.g.BlockMax;i++) {
			Index = gBasiGlobal.g.BlockIndex[i];
			if(Index > gBasiGlobal.gfsBlockSize)
				Index = ~(Index+1);
			if(Index > gBasiGlobal.gfsBlockSize) {
				SZ_LOG(LOG_ERROR,"入口地址[%d]错误\r\n",Index);
				gBasiGlobal.g.BlockIndex[i] = GFS_INDEX_NULL;
				continue;
			}
			gBasiGlobal.g.BlockIndex[i]=Index;
			j++;
		}
		if(j) {
			for(;i<GFS_FILE_MAX;i++)
				gBasiGlobal.g.BlockIndex[i] = GFS_INDEX_NULL;
			gfs_BalancedGlobalSave(1);	//更新引导区
		}
		#endif
		return;
	}
		
	LG("**Gfs MedianInitCheck(%d)\r\rn",gBasiGlobal.g.BlockMax);
	//--------------改造旧版本，兼容旧版本(向下兼容)-----------
	for(i=0,j=0;j<GFS_FILE_MAX;j++)
	{//----------------转码为正码-------------------
		if(gBasiGlobal.g.BlockIndex[j] == GFS_INDEX_NULL) 
			continue;
		#ifdef INDEX_COUNT_DOWN
		gBasiGlobal.g.BlockIndex[i++] = ~(gBasiGlobal.g.BlockIndex[j]+1);
		#else
		gBasiGlobal.g.BlockIndex[i++] = gBasiGlobal.g.BlockIndex[j];
		#endif
	}
	for(j=i;j<GFS_FILE_MAX;j++)
	{//-------------清空后面的内容-------------------
		gBasiGlobal.g.BlockIndex[j]=GFS_INDEX_NULL;
	}
	gBasiGlobal.g.BlockMax = i;
	//---------------排序---------------
	for(j=0;j<gBasiGlobal.g.BlockMax;j++) {
		gfs_FsReadblock(InversBlock(gBasiGlobal.g.BlockIndex[j]),0,&tName1,sizeof(DfGTreeFsFileName));
		for(i=j+1;i<gBasiGlobal.g.BlockMax;i++)
		{
			gfs_FsReadblock(InversBlock(gBasiGlobal.g.BlockIndex[i]),0,&tName2,sizeof(DfGTreeFsFileName));
			if(strcmp(tName1.filepath,tName2.filepath) > 0)
			{
				strcpy(tName1.filepath,tName2.filepath);
				Index=gBasiGlobal.g.BlockIndex[j];
				gBasiGlobal.g.BlockIndex[j]=gBasiGlobal.g.BlockIndex[i];
				gBasiGlobal.g.BlockIndex[i]=Index;
			}
		}
	}
	gBasiGlobal.g.PreMax = gBasiGlobal.g.BlockMax;
	gfs_BalancedGlobalSave(1);	//更新引导区
}
#else	//---Olde

u16 gfs_GetNewGuide(void)
{
	int i;
	if(gBasiGlobal.gfsBlockSize == 0)	
		return GFS_INDEX_NULL;
	for(i=0;i<GFS_FILE_MAX;i++)
	{
		if(gBasiGlobal.g.BlockIndex[i] == GFS_INDEX_NULL)
		{
			gBasiGlobal.g.BlockIndex[i] = GFS_BASIC_DATA;	//避免其它线程抢占入口
			return i;
		}
	}
	LG("gfs GetNewBlockNum i[%d] Err OK\r\n",i);
	return GFS_INDEX_NULL;
}
int Gfs_LoadIndexGuide(u16 IndexGuide,u16 IndexEntry)
{
	if(IndexGuide < GFS_FILE_MAX) {
		u16 oldIndex = gBasiGlobal.g.BlockIndex[IndexGuide];
		SetInversBlock(IndexEntry)
		gBasiGlobal.g.BlockIndex[IndexGuide] = IndexEntry;
		if(oldIndex == GFS_BASIC_DATA) {
			return 0;
		}
		if(IndexEntry == (IndexEntry&oldIndex)) {
			return 0;
		}
		return 1;
	}
	LG("###gfs LoadIndexSwitch IndexGuide[%d] IndexEntry[%d] Err\r\n",IndexGuide,((~IndexEntry)-1));
	return -1;
}

void gfs_FreeIndexGuide(u16 iGuide,u16 iEntry)
{
	if(iGuide < GFS_FILE_MAX)
		gBasiGlobal.g.BlockIndex[iGuide] = GFS_INDEX_NULL;
	gfs_ClearNullBit(iEntry);
}

u16 gfs_ScanFileName(gFsNameUnit *pName,const char *path)	//,char pathType
{
	int i;
	if(gBasiGlobal.gfsBlockSize == 0)	
		return GFS_INDEX_NULL;
	for(i=0;i<GFS_FILE_MAX;i++) {
		if(gBasiGlobal.g.BlockIndex[i] != GFS_INDEX_NULL) {
			gfs_FsReadblock(InversBlock(gBasiGlobal.g.BlockIndex[i]),0,pName,sizeof(DfGTreeFsFileName));
			//if(pName->fType != pathType) 
			//	continue;	//文件夹内容不能匹配
			if(strcmp(path,pName->f.filepath)==0) {
				return i;
			}
		}
	}
	return GFS_INDEX_NULL;
}

#endif

int gfs_CheckEraseBlockBit(int force)
{
	u16 i,iMax,b,bMax;
	u32 bitflag, UpFlag = 0;
	iMax=sizeof(gBasiGlobal.g.EraseBit)/sizeof(gBasiGlobal.g.EraseBit[0]);
	bMax=sizeof(gBasiGlobal.g.EraseBit[0])*8;
	if(gBasiGlobal.g.t.flagClear == 0xFF) force++;
	for(i=0;i<iMax;i++)
	{
		if(~gBasiGlobal.g.EraseBit[i])	//No 0xffffffff
		{
			bitflag=0x01;
			for(b=0;b<bMax;b++)
			{
				if(!(gBasiGlobal.g.EraseBit[i] & bitflag))
				{//-----察除前面被标记的块-------
					if(force)
					{//--非 FF 已经察除不需要再重复动作---
						gfs_FsEraseblock(i*bMax + b);
						UpFlag++;
					}
					gBasiGlobal.g.EraseBit[i] |= bitflag;
					gBasiGlobal.g.NullBit[i] |= bitflag;
				}
				bitflag <<= 1;			
			}
		}
	}
	if(UpFlag >0 && gBasiGlobal.g.t.flagClear == 0xFF)
	{//---当前位置标记已察除-----
		gBasiGlobal.g.t.flagClear=0x55; //标记 已经察除
		bitflag = gBasiGlobal.gfsCoutStart*GFS_BLOCK_SIZE + (sizeof(DfGTreeFsGlobal)*gBasiGlobal.gfsCoutIndex);
		SPI_Flash_Write(bitflag,&gBasiGlobal.g.t,sizeof(gBasiGlobal.g.t));
	}
	return UpFlag;
}

u16 gfs_GetNextNullBlock(void)
{
	u32 bitflag;
	u16 Ix,bMax,times;//IxMax,
	//IxMax=sizeof(gBasiGlobal.g.NullBit)/sizeof(gBasiGlobal.g.NullBit[0]);
	bMax=sizeof(gBasiGlobal.g.NullBit[0])*8;
	times = gBasiGlobal.gfsBlockSize;
	while(times--)
	{
		if(gBasiGlobal.gfsNewIndex >= gBasiGlobal.gfsBlockSize)
		{//----避免超出使用空间------
			#ifdef INDEX_COUNT_DOWN //Countdown
			gBasiGlobal.gfsNewIndex=gBasiGlobal.gfsBlockSize-1;
			#else
			gBasiGlobal.gfsNewIndex=0;
			#endif
		}
		Ix = gBasiGlobal.gfsNewIndex / bMax;
		bitflag = (0x01<<(gBasiGlobal.gfsNewIndex % bMax));
		if((bitflag & 0x01) && (gBasiGlobal.g.NullBit[Ix] == 0))
		{//---检查整块参数------
			#ifdef INDEX_COUNT_DOWN //Countdown
			gBasiGlobal.gfsNewIndex -= bMax;
			#else
			gBasiGlobal.gfsNewIndex += bMax;
			#endif
			times -= bMax; times++;
			if(times > gBasiGlobal.gfsBlockSize)
				break; 
			continue;
		}
		if(gBasiGlobal.g.NullBit[Ix] & bitflag) {
			gBasiGlobal.g.NullBit[Ix] &= ~bitflag;
			#ifdef INDEX_COUNT_DOWN //Countdown
			return gBasiGlobal.gfsNewIndex--;
			#else
			return gBasiGlobal.gfsNewIndex++;
			#endif
		}
		#ifdef INDEX_COUNT_DOWN //Countdown
		gBasiGlobal.gfsNewIndex--;
		#else
		gBasiGlobal.gfsNewIndex++;
		#endif
	}
	//TRACE("*****GetNextNullBlock ERR*[%d]**Is No BitSpace*****\r\n",gBasiGlobal.gfsNewIndex);
	//TRACE_HEX("NullBit",(u8*)gBasiGlobal.g.NullBit,IxMax*sizeof(gBasiGlobal.g.NullBit[0]));
	return GFS_INDEX_NULL;
}

void gfs_unrecord_erase(u16 IndexArray)
{
	u16 ei,b;
	if(IndexArray == GFS_INDEX_NULL)	//遇到一个 GFS_INDEX_NULL 就跳出来
		return;
	ei = IndexArray/(sizeof(gBasiGlobal.g.EraseBit[0])*8);
	if(ei >= (sizeof(gBasiGlobal.g.EraseBit)/sizeof(gBasiGlobal.g.EraseBit[0]))) {
		LG("gfs UndoRecordDelete EraseBlock[%d] tobig Err\r\n", IndexArray);
		return;
	}
	GFS_MUTEX_LOCK();
	b = IndexArray % (sizeof(gBasiGlobal.g.EraseBit[0])*8);
	/*
	if(gBasiGlobal.g.EraseBit[ei] & (0x01<<b))
	{
		TRACE("*** UndoRecordDelete [%d]", IndexArray);
	}*/
	gBasiGlobal.g.EraseBit[ei] |= (0x01<<b);
	GFS_MUTEX_UNLOCK();
}


int gfs_record_erase(u16 IndexArray)
{
	GFS_MUTEX_LOCK();
	int ret = gfs_RecordErase(IndexArray);
	GFS_MUTEX_UNLOCK();
	return ret;
}

void gfs_record_delete(u16* pIndexArray,int max)
{
	GFS_MUTEX_LOCK();
	for(int i=0;i<max;i++) { //一查到底部，避免重新写入长度的文件后面空间没有被清空--
		if(gfs_RecordErase(pIndexArray[i]))
			break;
		pIndexArray[i] = GFS_INDEX_NULL;
	}
	GFS_MUTEX_UNLOCK();
}

u16 gfs_get_block_index(u16 i)
{
	GFS_MUTEX_LOCK();
	int ret = InversBlock(gBasiGlobal.g.BlockIndex[i]);
	GFS_MUTEX_UNLOCK();
	return ret;
}

int gfs_check_erase_block_bit(int force)
{
	GFS_MUTEX_LOCK();
	int ret = gfs_CheckEraseBlockBit(force);
	GFS_MUTEX_UNLOCK();
	return ret;
}

u16 gfs_get_next_nullblock(void)
{
	GFS_MUTEX_LOCK();
	u16 ret = gfs_GetNextNullBlock();
	GFS_MUTEX_UNLOCK();
	return ret;
}

u16 gfs_get_new_guide(void)
{
	GFS_MUTEX_LOCK();
	u16 ret = gfs_GetNewGuide();
	GFS_MUTEX_UNLOCK();
	return ret;
}

void gfs_free_index_guide(u16 iGuide,u16 iEntry)
{
	GFS_MUTEX_LOCK();
	gfs_FreeIndexGuide(iGuide,iEntry);
	GFS_MUTEX_UNLOCK();
}


void gfs_ClearFile(u16 IndexGuide,u16 IndexEntry,u16* pGIndex,int gLen)
{
	GFS_MUTEX_LOCK();
	for(int i=0;i<gLen;i++) {
		if(gfs_RecordErase(pGIndex[i]))
			break;
	}
	gfs_RecordErase(IndexEntry);
	#ifdef GFS_MEDIAN_SCAN
	gfs_FreeIndexGuide(IndexGuide,IndexEntry);
	#else
	gfs_FreeIndexGuide(IndexGuide,GFS_INDEX_NULL);
	#endif
	gfs_BalancedGlobalSave(1);
	gfs_CheckEraseBlockBit(0);
	GFS_MUTEX_UNLOCK();
}


#ifdef GFS_RECORD_FUNTION
int gfs_RecordSpaceInit(DfgRcUnitHead *pHead,int num,int aSize)
{
	u16 i,blockNum;
	if((aSize<4) || (aSize+sizeof(DfgHeadCheck)) > GFS_BLOCK_SIZE) {
		LG(" RecordSpaceInit asize[%d] Err",aSize);
		return -1;
	}
	pHead->name.pgSize = DfGetBeiSu((aSize+sizeof(DfgHeadCheck)),GFS_PAGE_SIZE);
	pHead->name.PageNum = GFS_BLOCK_SIZE / pHead->name.pgSize;
	//----- 备用一个块，确保大于等于num数量不丢失 -------------------
	blockNum = 1 + (num / pHead->name.PageNum) + ((num % pHead->name.PageNum) != 0);
	//------检查所需空间块不得大于所管理的最大空间块-------------------
	if(blockNum > ARRAY_NUM(pHead->fdIndex)) {
		LG(" RecordSpaceInit blockNum[%d] Err[%d,%d]",blockNum,num,aSize);
		return -2;
	}
	pHead->name.PageMax = blockNum * pHead->name.PageNum;
	pHead->name.parLen = aSize;
	int ret = 0;
	GFS_MUTEX_LOCK();
	for(i=0;i<blockNum;i++) { //申请的需要的空间-
		pHead->fdIndex[i] = gfs_GetNextNullBlock();
		if(pHead->fdIndex[i] == GFS_INDEX_NULL) {
			SZ_LOG(LOG_ERROR,"RecordSpaceInit is no[%d<%d]\r\n",i,blockNum);
			while(i--) {
				gfs_ClearNullBit(pHead->fdIndex[i]);
				pHead->fdIndex[i]=GFS_INDEX_NULL;
			}
			ret = -3; break;
		}
	}
	pHead->name.blockNum = blockNum;
	GFS_MUTEX_UNLOCK();
	return ret;
}

int gfs_RecordNewSearch(DfgRcUnitHead *pHead)
{
	u16 block,offset,Index,PageMax;
	DfgHeadCheck head1,head2;
	head1.head = GFS_BASIC_NULL;
	PageMax = pHead->name.PageMax;
	for(Index=0;Index < PageMax ;Index++) {
		block = pHead->fdIndex[Index / pHead->name.PageNum];
		offset = (Index % pHead->name.PageNum)* pHead->name.pgSize;
		if(sizeof(DfgHeadCheck) > gfs_FsReadblock(block,offset,&head2,sizeof(DfgHeadCheck)))
			continue;
		if(head2.head == GFS_BASIC_DATA && head2.Index == Index) {
			if(head1.head == GFS_BASIC_NULL || (head2.count - head1.count) > 0) {
				head1.count = head2.count;
				head1.head = GFS_BASIC_DATA;
				head1.Index = head2.Index;	//借用pgSize 存 PageIndex
				continue;
			}
			break;
		}
	}
	if(head1.head == GFS_BASIC_DATA) {
		pHead->count = head1.count;
		pHead->PageIndex = head1.Index;
		//TRACE("Ok->PageIndex[%d]->count[%d]\r\n",head1.Index,head1.count);
		return pHead->name.parLen;
	}
	pHead->count = 0;
	pHead->PageIndex = 0;
	LG("##Err->PageIndex[%d],PageMax[%d]blockNum[%d]PageNum[%d]\r\n",Index,PageMax,pHead->name.blockNum,pHead->name.PageNum);
	return 0;
}

int gfs_RecordRead(DfgRcUnitBlock *pUnit,int PreIndex,void* pBuff)
{
	u16 block,offset;
	if(PreIndex >= pUnit->h.name.PageMax) return -3;
	if(PreIndex >= pUnit->h.count) return -4;
	PreIndex = (int)pUnit->h.PageIndex - PreIndex;
	if(PreIndex < 0) PreIndex += pUnit->h.name.PageMax;
	block = pUnit->h.fdIndex[PreIndex/pUnit->h.name.PageNum];
	offset = (PreIndex % pUnit->h.name.PageNum)*pUnit->h.name.pgSize;
	if(gfs_FsReadblock(block,offset,&pUnit->d,pUnit->h.name.pgSize) < pUnit->h.name.pgSize)
		return -1;
	if(pUnit->d.hg.head == GFS_BASIC_DATA && (int)pUnit->d.hg.Index == PreIndex) {
		if(pBuff) //可以允许 buff 为空
			memcpy(pBuff,pUnit->d.dg,pUnit->h.name.parLen);
		return pUnit->h.name.parLen;
	}
	return 0;
}

int gfs_RecordSave(DfgRcUnitBlock *pUnit,void* pBuff)
{
	u16 block,offset;
	if(pBuff)	//可以允许 buff 为空
		memcpy(pUnit->d.dg,pBuff,pUnit->h.name.parLen);
	while(1) {
		pUnit->h.count++;
		pUnit->h.PageIndex++;
		if(pUnit->h.PageIndex >= pUnit->h.name.PageMax)
			pUnit->h.PageIndex=0;
		//---------------计算位置并腾出空间-------------------------------
		block = pUnit->h.fdIndex[pUnit->h.PageIndex / pUnit->h.name.PageNum];
		offset = (pUnit->h.PageIndex % pUnit->h.name.PageNum)*pUnit->h.name.pgSize;
		if(offset == 0) {
			gfs_FsEraseblock(block);
		}
		//---------------------------------------------------
		pUnit->d.hg.head =	GFS_BASIC_DATA;
		pUnit->d.hg.count = pUnit->h.count;
		pUnit->d.hg.Index = pUnit->h.PageIndex;		
		if(gfs_FsWriteblock(block,offset,&pUnit->d,pUnit->h.name.pgSize) >= pUnit->h.name.pgSize)
			return pUnit->h.name.parLen;
		//--------------写入失败记录为坏块继续写---------------------
		pUnit->d.hg.head = GFS_BASIC_BAD;	//记录为坏块
		pUnit->d.hg.Index = GFS_BASIC_BAD;
		gfs_FsWriteblock(block,offset,&pUnit->d,sizeof(DfgHeadCheck));
	}
}
#endif

int gfs_BalancedGlobalInit(void)
{
	u32 Addr;
	DfGTreeFsGlobal gGlobalOldeData;
	if(gBasiGlobal.gfsCoutSize == 0) return -1;
	gBasiGlobal.gfsCoutIndex = gBasiGlobal.gfsCoutSize*(GFS_BLOCK_SIZE/sizeof(DfGTreeFsGlobal));
	while(gBasiGlobal.gfsCoutIndex--) {
		Addr=gBasiGlobal.gfsCoutStart*GFS_BLOCK_SIZE + (sizeof(DfGTreeFsGlobal)*gBasiGlobal.gfsCoutIndex);
		if(sizeof(gGlobalOldeData.t) == SPI_Flash_Read(Addr,&gGlobalOldeData.t,sizeof(gGlobalOldeData.t))) {
			if(gGlobalOldeData.t.head == GFS_BASIC_GUID && gGlobalOldeData.t.flagZ == GFS_FLAG_Z) {
				if(sizeof(gGlobalOldeData) == SPI_Flash_Read(Addr,&gGlobalOldeData,sizeof(gGlobalOldeData))) {
					#if(1)	//Test
					{
						u32		NewData[GFS_BIT_FLAG];	//空块 block
						u32		OldData[GFS_BIT_FLAG];	//需要察除的块
						int		i;
						for(i=0;i<GFS_BIT_FLAG;i++)
							NewData[i] =gBasiGlobal.g.NullBit[i]^gBasiGlobal.g.EraseBit[i];
						for(i=0;i<GFS_BIT_FLAG;i++)
							OldData[i] =gGlobalOldeData.NullBit[i]^gGlobalOldeData.EraseBit[i];
						
						if(memcmp_u32(OldData,NewData,sizeof(NewData)/sizeof(u32))) {
							LG_HEX("  gBasiGlobal.g",(u8*)&gBasiGlobal.g, sizeof(gBasiGlobal.g));
							LG_HEX("gGlobalOldeData",(u8*)&gGlobalOldeData, sizeof(gGlobalOldeData));
						}
					}
					#endif
					//TRACE("Global 3Read[%x]->[%d] [%X][%d] OK",Addr,gBasiGlobal.gfsCoutIndex,gGlobalOldeData.t.head,gGlobalOldeData.t.flagG);
					memcpy_u32((u32*)&gBasiGlobal.g,(u32*)&gGlobalOldeData,sizeof(DfGTreeFsGlobal)/sizeof(u32));
					#ifdef GFS_MEDIAN_SCAN
					Gfs_MedianInitCheck();
					#endif
					return sizeof(gBasiGlobal.g);
				}
			}
		}
	}
	//----------------引导块需要初始化-----------------------
	memset_u32((u32*)&gBasiGlobal.g,0xffffffff,sizeof(gBasiGlobal.g)/sizeof(u32));
	gBasiGlobal.g.t.head = GFS_BASIC_GUID;
	#ifdef INDEX_COUNT_DOWN //Countdown
	gBasiGlobal.g.t.index = gBasiGlobal.gfsBlockSize-1;
	#else
	gBasiGlobal.g.t.index = 0;
	#endif
	gBasiGlobal.g.t.flagZ = GFS_FLAG_Z; //不同文件系统头兼容性标记
	gBasiGlobal.gfsCoutIndex = 0;
	#ifdef GFS_MEDIAN_SCAN
	gBasiGlobal.g.BlockMax = 0;
	gBasiGlobal.g.PreMax = 0;
	#endif
	LG("-------BalancedGlobalInit*NULL------------");
	return 0;
}


int gfs_Init(u16 startCap,u16 fdSize,u16 countSize,int brFlag)	//startCap,fdSize,countSize->SPI_BLOCK_SIZE
{	
	if(GFS_BLOCK_SIZE % sizeof(DfGTreeFsGlobal)) {
		LG("##GFS_BIT_FLAG=%d,GFS_FILE_MAX=%d ->%d", GFS_BIT_FLAG, GFS_FILE_MAX, sizeof(DfGTreeFsGlobal));
		return -1;
	}
	if(fdSize <= countSize) return -2;
	if(fdSize <= 64) return -3;
	gBasiGlobal.gfsCoutStart = startCap;
	gBasiGlobal.gfsCoutSize = countSize;
	gBasiGlobal.gfsBlockStart = startCap+countSize;
	gBasiGlobal.gfsBlockSize = fdSize-countSize;
	if(gBasiGlobal.gfsBlockSize > sizeof(gBasiGlobal.g.NullBit)*8)
		return -4;	//超出管理空间
	LG("gfs_Init[%d,%d][%d->%d,%d]", sizeof(tFILE), sizeof(DfgFsUnitBlock),GFS_BIT_FLAG,gBasiGlobal.gfsBlockSize,sizeof(gBasiGlobal.g.NullBit)*8);
	#ifdef GFS_RECORD_FUNTION
	LG("->DfgRcUnitHead[%d]DfgRcUnitBlock[%d]", sizeof(DfgRcUnitHead), sizeof(DfgRcUnitBlock));
	#endif

	int ret = 0;
	GFS_MUTEX_LOCK();
	if(sizeof(gBasiGlobal.g) == gfs_BalancedGlobalInit()) {
		gfs_CheckEraseBlockBit(0);
		gBasiGlobal.gfsNewIndex=gBasiGlobal.g.t.index;
	}
	else if(brFlag) { //FLASH 第一次上电擦除整个FLASH块
		SPI_Flash_ERASE_ALL();
		gfs_BalancedGlobalSave(0);
		gBasiGlobal.gfsNewIndex=gBasiGlobal.g.t.index;
		ret = 2;
	}
	else {
		for(int i=0;i<countSize;i += (FLASH_BLOCK64_SIZE/FLASH_SECTOR_SIZE)) 
			SPI_Flash_ERASE_16Block((i+startCap)*GFS_BLOCK_SIZE);
		gfs_BalancedGlobalSave(0);
		gBasiGlobal.gfsNewIndex=gBasiGlobal.g.t.index;
		ret = 1;
	}
	GFS_MUTEX_UNLOCK();
	return ret;
}

int gfs_Fomat(char *pKey)
{
	u16 i,max;
	if(gBasiGlobal.gfsBlockSize < 16)
		return -1;
	max = gBasiGlobal.gfsCoutSize+gBasiGlobal.gfsBlockSize;
	for(i=0;i<max;i += (FLASH_BLOCK64_SIZE/FLASH_SECTOR_SIZE)) {
		//TRACE("ERASE[%x]...",gBasiGlobal.gfsCoutStart+i);
		SPI_Flash_ERASE_16Block((gBasiGlobal.gfsCoutStart+i)*GFS_BLOCK_SIZE);
	}
	GFS_MUTEX_LOCK();
	gfs_BalancedGlobalInit();
	gfs_BalancedGlobalSave(0);
	gBasiGlobal.gfsNewIndex=gBasiGlobal.g.t.index;
	GFS_MUTEX_UNLOCK();
	return 0;
}

//--------------------gfs_api------------------------------------------------
void gfs_balanced_global_save(int pNew)
{
	GFS_MUTEX_LOCK();
	gfs_BalancedGlobalSave(pNew);
	GFS_MUTEX_UNLOCK();
}

int gfs_SetOffset(gFILE pfd,int offset, int whence)
{
	if(whence == GFS_SEEK_CUR) {
		if((offset + pfd->fOffset) > pfd->fLen) return -2;
		pfd->fOffset += offset;
	}
	else {
		if(whence == GFS_SEEK_END) {
			offset = pfd->fLen - offset;
		}
		#if(GFS_BLOCK_SIZE > GTREE_FS_UNIT_SIZE)
		pfd->IndexB = 0;
		pfd->bOffet = sizeof(pfd->u.h);
		#else
		pfd->IndexB = 1;
		pfd->bOffet = 0;
		#endif
		pfd->fOffset = offset;
	}
	//-----------------------------------------
	#if(GFS_BLOCK_SIZE > GTREE_FS_UNIT_SIZE)
	int IndexMax =GFS_BLOCK_SIZE - pfd->bOffet;
	while(offset >= IndexMax) {
		offset -= IndexMax;
		pfd->IndexB ++;
		pfd->bOffet =0;
		IndexMax = GFS_BLOCK_SIZE;
	}
	#else
	while(offset >= GFS_BLOCK_SIZE) {
		offset -= GFS_BLOCK_SIZE;
		pfd->IndexB ++;
		pfd->bOffet =0;
	}
	#endif
	pfd->bOffet += offset;
	return 0;
}

int gfs_ExportAllpath(char *pOutName[],int MaxNum,char *pbuff)
{
	char *pOffset;
	gFsNameUnit tName;
	u16 i,blockMax,j;
	if(gBasiGlobal.gfsBlockSize == 0)	
		return -1;
	blockMax = sizeof(gBasiGlobal.g.BlockIndex)/sizeof(gBasiGlobal.g.BlockIndex[0]);
	pOffset = pbuff;
	for(j=0,i=0;i<blockMax;i++) {
		if(gBasiGlobal.g.BlockIndex[i] != GFS_INDEX_NULL) {
			gfs_FsReadblock(InversBlock(gBasiGlobal.g.BlockIndex[i]),0,&tName,sizeof(tName));
			if(pbuff) {
				pOutName[j++] = pOffset;
				strcpy(pOffset,tName.f.filepath);
				pOffset += strlen(pOffset)+1;
			}
			else {
				strcpy(pOutName[j++],tName.f.filepath);
			}
			if(j >= MaxNum) break;
		}
	}
	return j;
}

void Gfs_SetNullBit(u16 index,u32 *pBit32)
{
	pBit32[index / 32] &= ~(0x01<<(index & (32-1)));
}

int gfs_checkALL(void)
{
	u32 	NullBit[GFS_BIT_FLAG];	//空块 block
	DfgFsUnitBlock tfilePar;
	u32 offset,fileLen,AllfileLen=0;
	u32 fileNum=0,blockNUN=0,Lenzero=0;
	u16 i,blockMax,j,max;
	if(gBasiGlobal.gfsBlockSize == 0)	
		return GFS_INDEX_NULL;
	if(gBasiGlobal.g.BlockMax != gBasiGlobal.g.PreMax) {
		LG("###BlockMax[%d]!=PreMax[%d]\r\n",gBasiGlobal.g.BlockMax,gBasiGlobal.g.PreMax);
	}
	memset_u32(NullBit,0xFFFFFFFF,sizeof(NullBit)/4);
	blockMax = sizeof(gBasiGlobal.g.BlockIndex)/sizeof(gBasiGlobal.g.BlockIndex[0]);
	max = ARRAY_NUM(tfilePar.h.fdIndex);
	for(i=0;i<blockMax;i++) {
		if(gBasiGlobal.g.BlockIndex[i] != GFS_INDEX_NULL) {
			gfs_FsReadblock(InversBlock(gBasiGlobal.g.BlockIndex[i]),0,&tfilePar,sizeof(DfgFsUnitBlock));
			//tfileHead.name.fType
			#ifdef GFS_RECORD_FUNTION
			if(tfilePar.h.name.fType == GFS_TYPE_COT) {
				DfgRcUnitBlock *pCont = (DfgRcUnitBlock *)&tfilePar;
				fileLen = pCont->h.name.blockNum * sizeof(DfgFsUnitBlock);
			}
			else
			#endif
			{
				fileLen = REV_ENCOD(tfilePar.h.name.InvLen);
			}
			fileNum ++;
			blockNUN ++;
			#if(GTREE_FS_UNIT_SIZE < GFS_BLOCK_SIZE)
			offset = sizeof(tfilePar.fData);
			#else
			offset = 0;
			#endif
			Gfs_SetNullBit(InversBlock(gBasiGlobal.g.BlockIndex[i]),NullBit);
			for(j=0;j<max;j++) {	//while(j++)
				if(tfilePar.h.fdIndex[j] == GFS_INDEX_NULL) break;
				Gfs_SetNullBit(tfilePar.h.fdIndex[j],NullBit);
				offset += GFS_BLOCK_SIZE;
				blockNUN ++;
			}
			tfilePar.h.name.filepath[sizeof(tfilePar.h.name.filepath)-1]='\0';
			if(fileLen == 0) {
				LG("*1 Index[%d] Block[%d] is Zero name0[%x]\r\n",i,InversBlock(gBasiGlobal.g.BlockIndex[i]),tfilePar.h.name.filepath[0]);
				Lenzero++;
			}
			#if(GTREE_FS_UNIT_SIZE < GFS_BLOCK_SIZE)
			else if(fileLen <=	sizeof(tfilePar.fData) && offset > sizeof(tfilePar.fData)) {
				LG("#1[%d] name[%s] len[%d,%d]-[%d]\r\n",fileNum, tfilePar.h.name.filepath, fileLen, offset,j);
			}
			else if(fileLen > sizeof(tfilePar.fData) && (offset-sizeof(tfilePar.fData)) > DfGetBeiSu(fileLen-sizeof(tfilePar.fData),GFS_BLOCK_SIZE)) {
				LG("#2[%d] name[%s] len[%d,%d]-[%d]\r\n",fileNum, tfilePar.h.name.filepath, fileLen, offset,j);
			}
			#else
			else if(offset > DfGetBeiSu(fileLen,GFS_BLOCK_SIZE)) {
				LG("#2[%d] name[%s] len[%d,%d]-[%d]\r\n",fileNum, tfilePar.h.name.filepath, fileLen, offset,j);
			}
			#endif
			else {
				LG("Ok[%d] name[%s] len[%d,%d]-[%d]\r\n",fileNum,tfilePar.h.name.filepath,fileLen,offset,j);
			}
			AllfileLen += fileLen;
		}
	}
	LG("allfile num[%d] blockNUN[%d<%d] len[%d]\r\n",fileNum,blockNUN,gBasiGlobal.gfsBlockSize,AllfileLen);
	blockMax = sizeof(gBasiGlobal.g.NullBit)/sizeof(gBasiGlobal.g.NullBit[0]);
	for(i=0;i<blockMax;i++) {
		if(gBasiGlobal.g.EraseBit[i] != 0xFFFFFFFF) {
			LG("***EraseBit[%d]=[%X]\r\n",i,gBasiGlobal.g.EraseBit[i]);
		}
		if(NullBit[i] !=  gBasiGlobal.g.NullBit[i]) {
			LG("###NullBit[%d]=[%X != %X]\r\n",i,NullBit[i],gBasiGlobal.g.NullBit[i]);
		}
	}
	u32 buff[GFS_BLOCK_SIZE/4];
	for(i=0;i<gBasiGlobal.gfsBlockSize;i++) {
		if(GFS_BLOCK_SIZE > SPI_Flash_Read((gBasiGlobal.gfsBlockStart+i)*GFS_BLOCK_SIZE,buff,GFS_BLOCK_SIZE)) {
			LG("###Read[%d]=Err",i);
		}
		else {
			for(j=0;j<(GFS_BLOCK_SIZE/4);j++)
				if(buff[j] != 0xFFFFFFFF)
					break;
			if(j<(GFS_BLOCK_SIZE/4)) {
				LG("###Read[%d.%d][%X] No Erase",i,j,buff[j]);
			}
		}
	}
	return Lenzero;
}


void gfs_clearNullfile(void)
{
	DfgFsUnitHead tfileh;  //	GTREE_FS_UNIT_SIZE
	u16 i,blockMax;
	if(gBasiGlobal.gfsBlockSize == 0)	
		return;
	blockMax = sizeof(gBasiGlobal.g.BlockIndex)/sizeof(gBasiGlobal.g.BlockIndex[0]);
	for(i=0;i<blockMax;i++) {
		if(gBasiGlobal.g.BlockIndex[i] != GFS_INDEX_NULL) {
			gfs_FsReadblock(InversBlock(gBasiGlobal.g.BlockIndex[i]),0,&tfileh,sizeof(tfileh));
			if((REV_ENCOD(tfileh.name.InvLen)) == 0) {
				gfs_ClearFile(i,InversBlock(gBasiGlobal.g.BlockIndex[i]),tfileh.fdIndex,ARRAY_NUM(tfileh.fdIndex));
			}
		}
	}
}

#endif

